/*
 * mana (library)
 * Copyright (c) 2003 Shun Moriya <shun@mnu.sakura.ne.jp>
 *
 * The MIT License
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*!
 * @file
 * @brief	mana_streamクラスに関するヘッダーファイル
 *
 * このファイルはmana_streamクラスに関係するヘッダーファイルです。
 * mana_streamクラスはメモリストリーミングに関する操作を行ないます。
 *
 * @author	Shun Moriya <shun@mnu.sakura.ne.jp>
 */

#if !defined(___MANA_STREAM_H___)
#define ___MANA_STREAM_H___

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

#include <stddef.h>

/*!
 * @brief	mana_streamクラス
 *
 * mana_streamクラスはメモリストリーミングを表しています。
 *
 * C++でいうところのメンバー変数ですが、C言語なので全てpublicになっています。
 * 操作用の関数を用意しているので、それらの関数を利用して操作してください。
 */
typedef struct mana_stream
{
	char* buffer;			/*!< @brief バッファ */
	size_t allocated_size;	/*!< @brief 確保済みサイズ */
	size_t used_size;		/*!< @brief 使用済みサイズ */
	size_t pointer;			/*!< @brief ポップ先オフセットアドレス */
}mana_stream;

/*! @brief mana_stream オブジェクトの生成 */
extern mana_stream* mana_stream_create(void);

/*! @brief mana_stream オブジェクトの破棄 */
extern void mana_stream_destroy(mana_stream* self);

/* @brief ファイルからデータを読み込む */
int mana_stream_load(mana_stream* self, const char* filename);

/* @brief ファイルへデータを書き込む */
int mana_stream_save(mana_stream* self, const char* filename);

/*! @brief バッファの先頭アドレスを取得 */
extern void* mana_stream_get_buffer(const mana_stream* self);

/*! @brief バッファのアドレスを取得 */
extern void* mana_stream_index_at(const mana_stream* self, const size_t index);

/*! @brief 確保済みバッファサイズを取得 */
extern size_t mana_stream_get_allocated_size(const mana_stream* self);

/*! @brief 使用しているバッファサイズを取得 */
extern size_t mana_stream_get_used_size(const mana_stream* self);

/*! @brief charサイズデータをプッシュ */
extern void mana_stream_push_char(mana_stream* self, const char value);

/*! @brief shortサイズデータをプッシュ */
extern void mana_stream_push_short(mana_stream* self, const short value);

/*! @brief intサイズデータをプッシュ */
extern void mana_stream_push_integer(mana_stream* self, const int value);

/*! @brief unsigned charサイズデータをプッシュ */
extern void mana_stream_push_unsigned_char(mana_stream* self, const unsigned char value);

/*! @brief unsigned shortサイズデータをプッシュ */
extern void mana_stream_push_unsigned_short(mana_stream* self, const unsigned short value);

/*! @brief unsigned intサイズデータをプッシュ */
extern void mana_stream_push_unsigned_integer(mana_stream* self, const unsigned int value);

/*! @brief floatサイズデータをプッシュ */
extern void mana_stream_push_float(mana_stream* self, const float value);

/*! @brief 文字列をプッシュ */
extern void mana_stream_push_string(mana_stream* self, const char* text);

/*! @brief データをプッシュ */
extern void mana_stream_push_data(mana_stream* self, const void* pointer, const size_t size);

/*! @brief popポインタを巻き戻す */
extern void mana_stream_rewind(mana_stream* self);

/*! @brief charサイズデータをポップ */
extern char mana_stream_pop_char(mana_stream* self);

/*! @brief shortサイズデータをポップ */
extern short mana_stream_pop_short(mana_stream* self);

/*! @brief intサイズデータをポップ */
extern int mana_stream_pop_integer(mana_stream* self);

/*! @brief unsigned charサイズデータをポップ */
extern unsigned char mana_stream_pop_unsigned_char(mana_stream* self);

/*! @brief unsigned shortサイズデータをポップ */
extern unsigned short mana_stream_pop_unsigned_short(mana_stream* self);

/*! @brief unsigned intサイズデータをポップ */
extern unsigned int mana_stream_pop_unsigned_integer(mana_stream* self);

/*! @brief floatサイズデータをポップ */
extern float mana_stream_pop_float(mana_stream* self);

/*! @brief 文字列をポップ */
extern void mana_stream_pop_string(mana_stream* self, char* pointer, const size_t size);

/*! @brief データをポップ */
extern void mana_stream_pop_data(mana_stream* self, void* pointer, const size_t size);

/*! @brief charサイズデータを取得 */
extern char mana_stream_get_char(const mana_stream* self);

/*! @brief shortサイズデータを取得 */
extern short mana_stream_get_short(const mana_stream* self);

/*! @brief intサイズデータを取得 */
extern int mana_stream_get_integer(const mana_stream* self);

/*! @brief unsigned charサイズデータを取得 */
extern unsigned char mana_stream_get_unsigned_char(const mana_stream* self);

/*! @brief unsigned shortサイズデータを取得 */
extern unsigned short mana_stream_get_unsigned_short(const mana_stream* self);

/*! @brief unsigned intサイズデータを取得 */
extern unsigned int mana_stream_get_unsigned_integer(const mana_stream* self);

/*! @brief floatサイズデータを取得 */
extern float mana_stream_get_float(const mana_stream* self);

/*! @brief 文字列を取得 */
extern void mana_stream_get_string(const mana_stream* self, char* pointer, const size_t size);

/*! @brief 文字列のポインターを取得 */
extern const char* mana_stream_get_string_pointer(const mana_stream* self);

/*! @brief 文字列の長さを取得 */
extern size_t mana_stream_get_string_length(const mana_stream* self);

/*! @brief データを取得 */
extern void mana_stream_get_data(const mana_stream* self, void* pointer, const size_t size);

/*! @brief 参照ポインタを移動します */
extern void mana_steram_seek(mana_stream* self, const int offset);

/*! @brief 現在のポインターを記録します */
extern void mana_stream_mark(mana_stream* self);

/*! @brief 現在のポインターが mana_stream_mark した位置か調べます */
extern void mana_stream_check(mana_stream* self);

#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) || defined(c_plusplus)
}
#endif

#endif
